﻿//-----------------------------------------------------------------------
// <copyright>
//     Copyright (c) Artur Mustafin. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

using Expressions.Compiler;

namespace Math.Compiler.Expressions
{
    internal static partial class NonterminalsDefinition
    {
        // Forward declarations
        internal static Nonterminal<char> expression = "expression[t]";
        internal static Nonterminal<char> assigment_expression = "assigment-expression[t]";
        internal static Nonterminal<char> function_definition = "function-definition[t]";
        internal static Nonterminal<char> function = "function[t]";
        internal static Nonterminal<char> expression_parameters = "expression-paremeters[t]";
        internal static Nonterminal<char> reference = "reference[t]";
        internal static Nonterminal<char> function_name = "function-name[t]";
        internal static Nonterminal<char> function_arg = "function-arg[t]";
        internal static Nonterminal<char> function_arg_list = "function-arg-list[t]";
        internal static Nonterminal<char> function_arg_list_part = "function-arg-list-part[t]";
        internal static Nonterminal<char> alpha_digits = "alpha-digits[t]";
        internal static Nonterminal<char> alpha_digit = "alpha-digit[t]";
        internal static Nonterminal<char> decimal_digits = "decimal-digits[t]";
        internal static Nonterminal<char> decimal_digit = "decimal-digit[t]";
        internal static Nonterminal<char> real_literal = "real-literal[t]";
        internal static Nonterminal<char> real_literal_part = "real-literal-part[t]";
        internal static Nonterminal<char> real_part_decimal = "real-part-decimal[t]";
        internal static Nonterminal<char> real_part_fraction = "real-part-fraction[t]";
        internal static Nonterminal<char> real_part_exponent = "real-part-exponent[t]";
        internal static Nonterminal<char> real_sign_part = "real-sign-part[t]";
        internal static Nonterminal<char> real_type_suffix = "real-type-suffix[t]";
        internal static Nonterminal<char> E = "E[t]";
        internal static Nonterminal<char> Eopt = "E'[t]";
        internal static Nonterminal<char> T = "T[t]";
        internal static Nonterminal<char> Topt = "T'[t]";
        internal static Nonterminal<char> F = "F[t]";

        static NonterminalsDefinition()
        {
            E.Definition = _E();
            T.Definition = _T();
            Eopt.Definition = _Eopt();
            Topt.Definition = _Topt();
            F.Definition = _F();
            expression.Definition = _expression();
            expression_parameters.Definition = _expression_parameters();
            assigment_expression.Definition = _assigment_expression();
            function_definition.Definition = _function_definition();
            function_name.Definition = new Rules<char>()
            {
                () => function[false]
            };
            function.Definition = new Rules<char>()
            {
                () => alpha_digits[false]
            };
            function_arg.Definition = new Rules<char>()
            {
                () => E[false]
            };
            function_arg_list.Definition = new Rules<char>()
            {
                () => function_arg[false] + function_arg_list_part[true]
            };
            function_arg_list_part.Definition = new Rules<char>()
            {
                () => ',' + function_arg_list[false],
            };
            reference.Definition = new Rules<char> 
            {
                () => alpha_digits[false] + decimal_digits[false] 
            };
            real_literal_part.Definition = new Rules<char>
            {
                () => real_part_decimal[false] +  real_part_fraction[true] + real_part_exponent[true],
                () => real_part_fraction[false] + real_part_exponent[true],
            };
            real_literal.Definition = new Rules<char> { () => real_sign_part[true] + real_literal_part[false] };
            real_part_decimal.Definition = new Rules<char> { () => decimal_digits[false] };
            real_part_fraction.Definition = new Rules<char> { () => '.' + decimal_digits[false] };
            real_part_exponent.Definition = new Rules<char> { () => 'e' + real_sign_part[true] + decimal_digits[false] };
            real_sign_part.Definition = new Rules<char> { () => '+', () => '-' };
            alpha_digits.Definition = new Rules<char>
            {
                () => alpha_digit[false] + alpha_digits[true] 
            };
            alpha_digit.Definition = new Rules<char> 
            {
                () => 'A', 
                () => 'B', 
                () => 'C',
                () => 'D', 
                () => 'E', 
                () => 'F', 
                () => 'G', 
                () => 'H', 
                () => 'I', 
                () => 'J', 
                () => 'K',
                () => 'L', 
                () => 'M', 
                () => 'N', 
                () => 'O', 
                () => 'P',
                () => 'Q',
                () => 'R', 
                () => 'S', 
                () => 'T', 
                () => 'U', 
                () => 'V',
                () => 'W', 
                () => 'X',
                () => 'Y', 
                () => 'Z' 
            };
            decimal_digits.Definition = new Rules<char> 
            {
                () => decimal_digit[false] + decimal_digits[true]
            };
            decimal_digit.Definition = new Rules<char> 
            {
                () => '0', 
                () => '1',
                () => '2', 
                () => '3', 
                () => '4', 
                () => '5', 
                () => '6', 
                () => '7', 
                () => '8', 
                () => '9' 
            };
        }
    }
}
